]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
Rename ViewSelector to SearchController
authorGeorges Basile Stavracas Neto <georges.stavracas@gmail.com>
Fri, 15 Jan 2021 12:59:58 +0000 (09:59 -0300)
committerMarge Bot <marge-bot@gnome.org>
Thu, 11 Feb 2021 21:14:36 +0000 (21:14 +0000)
Rename ViewSelector to SearchController, since ViewSelector now effectively
only handles search. Rename the file correspondingly as well.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1667>

js/js-resources.gresource.xml
js/ui/overviewControls.js
js/ui/searchController.js [new file with mode: 0644]
js/ui/viewSelector.js [deleted file]
po/POTFILES.in

index 45b5de4362db6b92b35a34585554ccb4c4df32c7..e65e0e9cfd722d5eb5118851b0b2aafd48e53f79 100644 (file)
@@ -94,6 +94,7 @@
     <file>ui/screenshot.js</file>
     <file>ui/scripting.js</file>
     <file>ui/search.js</file>
+    <file>ui/searchController.js</file>
     <file>ui/sessionMode.js</file>
     <file>ui/shellDBus.js</file>
     <file>ui/shellEntry.js</file>
     <file>ui/switchMonitor.js</file>
     <file>ui/unlockDialog.js</file>
     <file>ui/userWidget.js</file>
-    <file>ui/viewSelector.js</file>
     <file>ui/welcomeDialog.js</file>
     <file>ui/windowAttentionHandler.js</file>
     <file>ui/windowMenu.js</file>
index 4e2c3f8cdb8f7b0f633a022d01a868edc02cc1b1..dcc93bb44f8b6ea49b85651cc232c73f7797d5b1 100644 (file)
@@ -7,8 +7,8 @@ const AppDisplay = imports.ui.appDisplay;
 const Dash = imports.ui.dash;
 const Main = imports.ui.main;
 const Overview = imports.ui.overview;
+const SearchController = imports.ui.searchController;
 const Util = imports.misc.util;
-const ViewSelector = imports.ui.viewSelector;
 const WindowManager = imports.ui.windowManager;
 const WorkspaceThumbnail = imports.ui.workspaceThumbnail;
 const WorkspacesView = imports.ui.workspacesView;
@@ -26,7 +26,7 @@ var ControlsState = {
 var ControlsManagerLayout = GObject.registerClass(
 class ControlsManagerLayout extends Clutter.BoxLayout {
     _init(searchEntry, appDisplay, workspacesDisplay, workspacesThumbnails,
-        viewSelector, dash, stateAdjustment) {
+        searchController, dash, stateAdjustment) {
         super._init({ orientation: Clutter.Orientation.VERTICAL });
 
         this._appDisplay = appDisplay;
@@ -34,7 +34,7 @@ class ControlsManagerLayout extends Clutter.BoxLayout {
         this._workspacesThumbnails = workspacesThumbnails;
         this._stateAdjustment = stateAdjustment;
         this._searchEntry = searchEntry;
-        this._viewSelector = viewSelector;
+        this._searchController = searchController;
         this._dash = dash;
 
         this._cachedWorkspaceBoxes = new Map();
@@ -178,11 +178,11 @@ class ControlsManagerLayout extends Clutter.BoxLayout {
         }
         this._appDisplay.allocate(appDisplayBox);
 
-        // ViewSelector
+        // Search
         childBox.set_origin(0, searchHeight + spacing);
         childBox.set_size(width, availableHeight);
 
-        this._viewSelector.allocate(childBox);
+        this._searchController.allocate(childBox);
     }
 
     getWorkspacesBoxForState(state) {
@@ -285,9 +285,10 @@ class ControlsManager extends St.Widget {
             workspaceManager.connect('notify::n-workspaces',
                 this._updateAdjustment.bind(this));
 
-        this.viewSelector = new ViewSelector.ViewSelector(this._searchEntry,
+        this._searchController = new SearchController.SearchController(
+            this._searchEntry,
             this.dash.showAppsButton);
-        this.viewSelector.connect('notify::search-active', this._onSearchChanged.bind(this));
+        this._searchController.connect('notify::search-active', this._onSearchChanged.bind(this));
 
         this._thumbnailsBox =
             new WorkspaceThumbnail.ThumbnailsBox(this._workspaceAdjustment);
@@ -300,7 +301,7 @@ class ControlsManager extends St.Widget {
         this.add_child(searchEntryBin);
         this.add_child(this._appDisplay);
         this.add_child(this.dash);
-        this.add_child(this.viewSelector);
+        this.add_child(this._searchController);
         this.add_child(this._thumbnailsBox);
         this.add_child(this._workspacesDisplay);
 
@@ -308,7 +309,7 @@ class ControlsManager extends St.Widget {
             this._appDisplay,
             this._workspacesDisplay,
             this._thumbnailsBox,
-            this.viewSelector,
+            this._searchController,
             this.dash,
             this._stateAdjustment);
 
@@ -402,7 +403,7 @@ class ControlsManager extends St.Widget {
     }
 
     _updateThumbnailsBox(animate = false) {
-        const { searchActive } = this.viewSelector;
+        const { searchActive } = this._searchController;
         const [opacity, scale, translationY] = this._getThumbnailsBoxParams();
 
         const thumbnailsBoxVisible = !searchActive && opacity !== 0;
@@ -442,14 +443,14 @@ class ControlsManager extends St.Widget {
     }
 
     _onSearchChanged() {
-        const { searchActive } = this.viewSelector;
+        const { searchActive } = this._searchController;
 
         if (!searchActive) {
             this._appDisplay.show();
             this._workspacesDisplay.reactive = true;
             this._workspacesDisplay.setPrimaryWorkspaceVisible(true);
         } else {
-            this.viewSelector.show();
+            this._searchController.show();
         }
 
         this._updateThumbnailsBox(true);
@@ -469,11 +470,11 @@ class ControlsManager extends St.Widget {
                 this._workspacesDisplay.setPrimaryWorkspaceVisible(!searchActive);
             },
         });
-        this.viewSelector.ease({
+        this._searchController.ease({
             opacity: searchActive ? 255 : 0,
             duration: SIDE_CONTROLS_ANIMATION_TIME,
             mode: Clutter.AnimationMode.EASE_OUT_QUAD,
-            onComplete: () => (this.viewSelector.visible = searchActive),
+            onComplete: () => (this._searchController.visible = searchActive),
         });
     }
 
@@ -526,7 +527,7 @@ class ControlsManager extends St.Widget {
     animateToOverview(state, callback) {
         this._ignoreShowAppsButtonToggle = true;
 
-        this.viewSelector.prepareToEnterOverview();
+        this._searchController.prepareToEnterOverview();
         this._workspacesDisplay.prepareToEnterOverview();
         if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows())
             Main.overview.fadeOutDesktop();
diff --git a/js/ui/searchController.js b/js/ui/searchController.js
new file mode 100644 (file)
index 0000000..75e27d0
--- /dev/null
@@ -0,0 +1,334 @@
+// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
+/* exported SearchController */
+
+const { Clutter, GObject, St } = imports.gi;
+
+const Main = imports.ui.main;
+const Search = imports.ui.search;
+const ShellEntry = imports.ui.shellEntry;
+
+var FocusTrap = GObject.registerClass(
+class FocusTrap extends St.Widget {
+    vfunc_navigate_focus(from, direction) {
+        if (direction == St.DirectionType.TAB_FORWARD ||
+            direction == St.DirectionType.TAB_BACKWARD)
+            return super.vfunc_navigate_focus(from, direction);
+        return false;
+    }
+});
+
+function getTermsForSearchString(searchString) {
+    searchString = searchString.replace(/^\s+/g, '').replace(/\s+$/g, '');
+    if (searchString == '')
+        return [];
+
+    let terms = searchString.split(/\s+/);
+    return terms;
+}
+
+var SearchController = GObject.registerClass({
+    Properties: {
+        'search-active': GObject.ParamSpec.boolean(
+            'search-active', 'search-active', 'search-active',
+            GObject.ParamFlags.READABLE,
+            false),
+    },
+}, class SearchController extends St.Widget {
+    _init(searchEntry, showAppsButton) {
+        super._init({
+            name: 'searchController',
+            layout_manager: new Clutter.BinLayout(),
+            x_expand: true,
+            y_expand: true,
+            visible: false,
+        });
+
+        this._showAppsButton = showAppsButton;
+        this._showAppsButton.connect('notify::checked', this._onShowAppsButtonToggled.bind(this));
+
+        this._activePage = null;
+
+        this._searchActive = false;
+
+        this._entry = searchEntry;
+        ShellEntry.addContextMenu(this._entry);
+
+        this._text = this._entry.clutter_text;
+        this._text.connect('text-changed', this._onTextChanged.bind(this));
+        this._text.connect('key-press-event', this._onKeyPress.bind(this));
+        this._text.connect('key-focus-in', () => {
+            this._searchResults.highlightDefault(true);
+        });
+        this._text.connect('key-focus-out', () => {
+            this._searchResults.highlightDefault(false);
+        });
+        this._entry.connect('popup-menu', () => {
+            if (!this._searchActive)
+                return;
+
+            this._entry.menu.close();
+            this._searchResults.popupMenuDefault();
+        });
+        this._entry.connect('notify::mapped', this._onMapped.bind(this));
+        global.stage.connect('notify::key-focus', this._onStageKeyFocusChanged.bind(this));
+
+        this._entry.set_primary_icon(new St.Icon({ style_class: 'search-entry-icon',
+                                                   icon_name: 'edit-find-symbolic' }));
+        this._clearIcon = new St.Icon({ style_class: 'search-entry-icon',
+                                        icon_name: 'edit-clear-symbolic' });
+
+        this._iconClickedId = 0;
+        this._capturedEventId = 0;
+
+        this._searchResults = new Search.SearchResultsView();
+        this.add_child(this._searchResults);
+        Main.ctrlAltTabManager.addGroup(this._entry, _('Search'), 'edit-find-symbolic');
+
+        // Since the entry isn't inside the results container we install this
+        // dummy widget as the last results container child so that we can
+        // include the entry in the keynav tab path
+        this._focusTrap = new FocusTrap({ can_focus: true });
+        this._focusTrap.connect('key-focus-in', () => {
+            this._entry.grab_key_focus();
+        });
+        this._searchResults.add_actor(this._focusTrap);
+
+        global.focus_manager.add_group(this._searchResults);
+
+        this._stageKeyPressId = 0;
+        Main.overview.connect('showing', () => {
+            this._stageKeyPressId = global.stage.connect('key-press-event',
+                                                         this._onStageKeyPress.bind(this));
+        });
+        Main.overview.connect('hiding', () => {
+            if (this._stageKeyPressId != 0) {
+                global.stage.disconnect(this._stageKeyPressId);
+                this._stageKeyPressId = 0;
+            }
+        });
+    }
+
+    prepareToEnterOverview() {
+        this.reset();
+        this._setSearchActive(false);
+    }
+
+    vfunc_unmap() {
+        this.reset();
+
+        super.vfunc_unmap();
+    }
+
+    _setSearchActive(searchActive) {
+        if (this._searchActive === searchActive)
+            return;
+
+        this._searchActive = searchActive;
+        this.notify('search-active');
+    }
+
+    _onShowAppsButtonToggled() {
+        this._setSearchActive(false);
+    }
+
+    _onStageKeyPress(actor, event) {
+        // Ignore events while anything but the overview has
+        // pushed a modal (system modals, looking glass, ...)
+        if (Main.modalCount > 1)
+            return Clutter.EVENT_PROPAGATE;
+
+        let symbol = event.get_key_symbol();
+
+        if (symbol === Clutter.KEY_Escape) {
+            if (this._searchActive)
+                this.reset();
+            else if (this._showAppsButton.checked)
+                this._showAppsButton.checked = false;
+            else
+                Main.overview.hide();
+            return Clutter.EVENT_STOP;
+        } else if (this._shouldTriggerSearch(symbol)) {
+            this.startSearch(event);
+        } else if (!this._searchActive && !global.stage.key_focus) {
+            if (symbol === Clutter.KEY_Tab || symbol === Clutter.KEY_Down) {
+                this._activePage.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
+                return Clutter.EVENT_STOP;
+            } else if (symbol === Clutter.KEY_ISO_Left_Tab) {
+                this._activePage.navigate_focus(null, St.DirectionType.TAB_BACKWARD, false);
+                return Clutter.EVENT_STOP;
+            }
+        }
+        return Clutter.EVENT_PROPAGATE;
+    }
+
+    _searchCancelled() {
+        this._setSearchActive(false);
+
+        // Leave the entry focused when it doesn't have any text;
+        // when replacing a selected search term, Clutter emits
+        // two 'text-changed' signals, one for deleting the previous
+        // text and one for the new one - the second one is handled
+        // incorrectly when we remove focus
+        // (https://bugzilla.gnome.org/show_bug.cgi?id=636341) */
+        if (this._text.text != '')
+            this.reset();
+    }
+
+    reset() {
+        // Don't drop the key focus on Clutter's side if anything but the
+        // overview has pushed a modal (e.g. system modals when activated using
+        // the overview).
+        if (Main.modalCount <= 1)
+            global.stage.set_key_focus(null);
+
+        this._entry.text = '';
+
+        this._text.set_cursor_visible(true);
+        this._text.set_selection(0, 0);
+    }
+
+    _onStageKeyFocusChanged() {
+        let focus = global.stage.get_key_focus();
+        let appearFocused = this._entry.contains(focus) ||
+                             this._searchResults.contains(focus);
+
+        this._text.set_cursor_visible(appearFocused);
+
+        if (appearFocused)
+            this._entry.add_style_pseudo_class('focus');
+        else
+            this._entry.remove_style_pseudo_class('focus');
+    }
+
+    _onMapped() {
+        if (this._entry.mapped) {
+            // Enable 'find-as-you-type'
+            this._capturedEventId = global.stage.connect('captured-event',
+                                                         this._onCapturedEvent.bind(this));
+            this._text.set_cursor_visible(true);
+            this._text.set_selection(0, 0);
+        } else {
+            // Disable 'find-as-you-type'
+            if (this._capturedEventId > 0)
+                global.stage.disconnect(this._capturedEventId);
+            this._capturedEventId = 0;
+        }
+    }
+
+    _shouldTriggerSearch(symbol) {
+        if (symbol === Clutter.KEY_Multi_key)
+            return true;
+
+        if (symbol === Clutter.KEY_BackSpace && this._searchActive)
+            return true;
+
+        let unicode = Clutter.keysym_to_unicode(symbol);
+        if (unicode == 0)
+            return false;
+
+        if (getTermsForSearchString(String.fromCharCode(unicode)).length > 0)
+            return true;
+
+        return false;
+    }
+
+    startSearch(event) {
+        global.stage.set_key_focus(this._text);
+
+        let synthEvent = event.copy();
+        synthEvent.set_source(this._text);
+        this._text.event(synthEvent, false);
+    }
+
+    // the entry does not show the hint
+    _isActivated() {
+        return this._text.text == this._entry.get_text();
+    }
+
+    _onTextChanged() {
+        let terms = getTermsForSearchString(this._entry.get_text());
+
+        const searchActive = terms.length > 0;
+        this._searchResults.setTerms(terms);
+
+        if (searchActive) {
+            this._setSearchActive(true);
+
+            this._entry.set_secondary_icon(this._clearIcon);
+
+            if (this._iconClickedId == 0) {
+                this._iconClickedId = this._entry.connect('secondary-icon-clicked',
+                                                          this.reset.bind(this));
+            }
+        } else {
+            if (this._iconClickedId > 0) {
+                this._entry.disconnect(this._iconClickedId);
+                this._iconClickedId = 0;
+            }
+
+            this._entry.set_secondary_icon(null);
+            this._searchCancelled();
+        }
+    }
+
+    _onKeyPress(entry, event) {
+        let symbol = event.get_key_symbol();
+        if (symbol === Clutter.KEY_Escape) {
+            if (this._isActivated()) {
+                this.reset();
+                return Clutter.EVENT_STOP;
+            }
+        } else if (this._searchActive) {
+            let arrowNext, nextDirection;
+            if (entry.get_text_direction() == Clutter.TextDirection.RTL) {
+                arrowNext = Clutter.KEY_Left;
+                nextDirection = St.DirectionType.LEFT;
+            } else {
+                arrowNext = Clutter.KEY_Right;
+                nextDirection = St.DirectionType.RIGHT;
+            }
+
+            if (symbol === Clutter.KEY_Tab) {
+                this._searchResults.navigateFocus(St.DirectionType.TAB_FORWARD);
+                return Clutter.EVENT_STOP;
+            } else if (symbol === Clutter.KEY_ISO_Left_Tab) {
+                this._focusTrap.can_focus = false;
+                this._searchResults.navigateFocus(St.DirectionType.TAB_BACKWARD);
+                this._focusTrap.can_focus = true;
+                return Clutter.EVENT_STOP;
+            } else if (symbol === Clutter.KEY_Down) {
+                this._searchResults.navigateFocus(St.DirectionType.DOWN);
+                return Clutter.EVENT_STOP;
+            } else if (symbol == arrowNext && this._text.position == -1) {
+                this._searchResults.navigateFocus(nextDirection);
+                return Clutter.EVENT_STOP;
+            } else if (symbol === Clutter.KEY_Return || symbol === Clutter.KEY_KP_Enter) {
+                this._searchResults.activateDefault();
+                return Clutter.EVENT_STOP;
+            }
+        }
+        return Clutter.EVENT_PROPAGATE;
+    }
+
+    _onCapturedEvent(actor, event) {
+        if (event.type() == Clutter.EventType.BUTTON_PRESS) {
+            let source = event.get_source();
+            if (source != this._text &&
+                this._text.has_key_focus() &&
+                this._text.text == '' &&
+                !this._text.has_preedit() &&
+                !Main.layoutManager.keyboardBox.contains(source)) {
+                // the user clicked outside after activating the entry, but
+                // with no search term entered and no keyboard button pressed
+                // - cancel the search
+                this.reset();
+            }
+        }
+
+        return Clutter.EVENT_PROPAGATE;
+    }
+
+    get searchActive() {
+        return this._searchActive;
+    }
+});
diff --git a/js/ui/viewSelector.js b/js/ui/viewSelector.js
deleted file mode 100644 (file)
index 210598d..0000000
+++ /dev/null
@@ -1,334 +0,0 @@
-// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
-/* exported ViewSelector */
-
-const { Clutter, GObject, St } = imports.gi;
-
-const Main = imports.ui.main;
-const Search = imports.ui.search;
-const ShellEntry = imports.ui.shellEntry;
-
-var FocusTrap = GObject.registerClass(
-class FocusTrap extends St.Widget {
-    vfunc_navigate_focus(from, direction) {
-        if (direction == St.DirectionType.TAB_FORWARD ||
-            direction == St.DirectionType.TAB_BACKWARD)
-            return super.vfunc_navigate_focus(from, direction);
-        return false;
-    }
-});
-
-function getTermsForSearchString(searchString) {
-    searchString = searchString.replace(/^\s+/g, '').replace(/\s+$/g, '');
-    if (searchString == '')
-        return [];
-
-    let terms = searchString.split(/\s+/);
-    return terms;
-}
-
-var ViewSelector = GObject.registerClass({
-    Properties: {
-        'search-active': GObject.ParamSpec.boolean(
-            'search-active', 'search-active', 'search-active',
-            GObject.ParamFlags.READABLE,
-            false),
-    },
-}, class ViewSelector extends St.Widget {
-    _init(searchEntry, showAppsButton) {
-        super._init({
-            name: 'viewSelector',
-            layout_manager: new Clutter.BinLayout(),
-            x_expand: true,
-            y_expand: true,
-            visible: false,
-        });
-
-        this._showAppsButton = showAppsButton;
-        this._showAppsButton.connect('notify::checked', this._onShowAppsButtonToggled.bind(this));
-
-        this._activePage = null;
-
-        this._searchActive = false;
-
-        this._entry = searchEntry;
-        ShellEntry.addContextMenu(this._entry);
-
-        this._text = this._entry.clutter_text;
-        this._text.connect('text-changed', this._onTextChanged.bind(this));
-        this._text.connect('key-press-event', this._onKeyPress.bind(this));
-        this._text.connect('key-focus-in', () => {
-            this._searchResults.highlightDefault(true);
-        });
-        this._text.connect('key-focus-out', () => {
-            this._searchResults.highlightDefault(false);
-        });
-        this._entry.connect('popup-menu', () => {
-            if (!this._searchActive)
-                return;
-
-            this._entry.menu.close();
-            this._searchResults.popupMenuDefault();
-        });
-        this._entry.connect('notify::mapped', this._onMapped.bind(this));
-        global.stage.connect('notify::key-focus', this._onStageKeyFocusChanged.bind(this));
-
-        this._entry.set_primary_icon(new St.Icon({ style_class: 'search-entry-icon',
-                                                   icon_name: 'edit-find-symbolic' }));
-        this._clearIcon = new St.Icon({ style_class: 'search-entry-icon',
-                                        icon_name: 'edit-clear-symbolic' });
-
-        this._iconClickedId = 0;
-        this._capturedEventId = 0;
-
-        this._searchResults = new Search.SearchResultsView();
-        this.add_child(this._searchResults);
-        Main.ctrlAltTabManager.addGroup(this._entry, _('Search'), 'edit-find-symbolic');
-
-        // Since the entry isn't inside the results container we install this
-        // dummy widget as the last results container child so that we can
-        // include the entry in the keynav tab path
-        this._focusTrap = new FocusTrap({ can_focus: true });
-        this._focusTrap.connect('key-focus-in', () => {
-            this._entry.grab_key_focus();
-        });
-        this._searchResults.add_actor(this._focusTrap);
-
-        global.focus_manager.add_group(this._searchResults);
-
-        this._stageKeyPressId = 0;
-        Main.overview.connect('showing', () => {
-            this._stageKeyPressId = global.stage.connect('key-press-event',
-                                                         this._onStageKeyPress.bind(this));
-        });
-        Main.overview.connect('hiding', () => {
-            if (this._stageKeyPressId != 0) {
-                global.stage.disconnect(this._stageKeyPressId);
-                this._stageKeyPressId = 0;
-            }
-        });
-    }
-
-    prepareToEnterOverview() {
-        this.reset();
-        this._setSearchActive(false);
-    }
-
-    vfunc_unmap() {
-        this.reset();
-
-        super.vfunc_unmap();
-    }
-
-    _setSearchActive(searchActive) {
-        if (this._searchActive === searchActive)
-            return;
-
-        this._searchActive = searchActive;
-        this.notify('search-active');
-    }
-
-    _onShowAppsButtonToggled() {
-        this._setSearchActive(false);
-    }
-
-    _onStageKeyPress(actor, event) {
-        // Ignore events while anything but the overview has
-        // pushed a modal (system modals, looking glass, ...)
-        if (Main.modalCount > 1)
-            return Clutter.EVENT_PROPAGATE;
-
-        let symbol = event.get_key_symbol();
-
-        if (symbol === Clutter.KEY_Escape) {
-            if (this._searchActive)
-                this.reset();
-            else if (this._showAppsButton.checked)
-                this._showAppsButton.checked = false;
-            else
-                Main.overview.hide();
-            return Clutter.EVENT_STOP;
-        } else if (this._shouldTriggerSearch(symbol)) {
-            this.startSearch(event);
-        } else if (!this._searchActive && !global.stage.key_focus) {
-            if (symbol === Clutter.KEY_Tab || symbol === Clutter.KEY_Down) {
-                this._activePage.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
-                return Clutter.EVENT_STOP;
-            } else if (symbol === Clutter.KEY_ISO_Left_Tab) {
-                this._activePage.navigate_focus(null, St.DirectionType.TAB_BACKWARD, false);
-                return Clutter.EVENT_STOP;
-            }
-        }
-        return Clutter.EVENT_PROPAGATE;
-    }
-
-    _searchCancelled() {
-        this._setSearchActive(false);
-
-        // Leave the entry focused when it doesn't have any text;
-        // when replacing a selected search term, Clutter emits
-        // two 'text-changed' signals, one for deleting the previous
-        // text and one for the new one - the second one is handled
-        // incorrectly when we remove focus
-        // (https://bugzilla.gnome.org/show_bug.cgi?id=636341) */
-        if (this._text.text != '')
-            this.reset();
-    }
-
-    reset() {
-        // Don't drop the key focus on Clutter's side if anything but the
-        // overview has pushed a modal (e.g. system modals when activated using
-        // the overview).
-        if (Main.modalCount <= 1)
-            global.stage.set_key_focus(null);
-
-        this._entry.text = '';
-
-        this._text.set_cursor_visible(true);
-        this._text.set_selection(0, 0);
-    }
-
-    _onStageKeyFocusChanged() {
-        let focus = global.stage.get_key_focus();
-        let appearFocused = this._entry.contains(focus) ||
-                             this._searchResults.contains(focus);
-
-        this._text.set_cursor_visible(appearFocused);
-
-        if (appearFocused)
-            this._entry.add_style_pseudo_class('focus');
-        else
-            this._entry.remove_style_pseudo_class('focus');
-    }
-
-    _onMapped() {
-        if (this._entry.mapped) {
-            // Enable 'find-as-you-type'
-            this._capturedEventId = global.stage.connect('captured-event',
-                                                         this._onCapturedEvent.bind(this));
-            this._text.set_cursor_visible(true);
-            this._text.set_selection(0, 0);
-        } else {
-            // Disable 'find-as-you-type'
-            if (this._capturedEventId > 0)
-                global.stage.disconnect(this._capturedEventId);
-            this._capturedEventId = 0;
-        }
-    }
-
-    _shouldTriggerSearch(symbol) {
-        if (symbol === Clutter.KEY_Multi_key)
-            return true;
-
-        if (symbol === Clutter.KEY_BackSpace && this._searchActive)
-            return true;
-
-        let unicode = Clutter.keysym_to_unicode(symbol);
-        if (unicode == 0)
-            return false;
-
-        if (getTermsForSearchString(String.fromCharCode(unicode)).length > 0)
-            return true;
-
-        return false;
-    }
-
-    startSearch(event) {
-        global.stage.set_key_focus(this._text);
-
-        let synthEvent = event.copy();
-        synthEvent.set_source(this._text);
-        this._text.event(synthEvent, false);
-    }
-
-    // the entry does not show the hint
-    _isActivated() {
-        return this._text.text == this._entry.get_text();
-    }
-
-    _onTextChanged() {
-        let terms = getTermsForSearchString(this._entry.get_text());
-
-        const searchActive = terms.length > 0;
-        this._searchResults.setTerms(terms);
-
-        if (searchActive) {
-            this._setSearchActive(true);
-
-            this._entry.set_secondary_icon(this._clearIcon);
-
-            if (this._iconClickedId == 0) {
-                this._iconClickedId = this._entry.connect('secondary-icon-clicked',
-                                                          this.reset.bind(this));
-            }
-        } else {
-            if (this._iconClickedId > 0) {
-                this._entry.disconnect(this._iconClickedId);
-                this._iconClickedId = 0;
-            }
-
-            this._entry.set_secondary_icon(null);
-            this._searchCancelled();
-        }
-    }
-
-    _onKeyPress(entry, event) {
-        let symbol = event.get_key_symbol();
-        if (symbol === Clutter.KEY_Escape) {
-            if (this._isActivated()) {
-                this.reset();
-                return Clutter.EVENT_STOP;
-            }
-        } else if (this._searchActive) {
-            let arrowNext, nextDirection;
-            if (entry.get_text_direction() == Clutter.TextDirection.RTL) {
-                arrowNext = Clutter.KEY_Left;
-                nextDirection = St.DirectionType.LEFT;
-            } else {
-                arrowNext = Clutter.KEY_Right;
-                nextDirection = St.DirectionType.RIGHT;
-            }
-
-            if (symbol === Clutter.KEY_Tab) {
-                this._searchResults.navigateFocus(St.DirectionType.TAB_FORWARD);
-                return Clutter.EVENT_STOP;
-            } else if (symbol === Clutter.KEY_ISO_Left_Tab) {
-                this._focusTrap.can_focus = false;
-                this._searchResults.navigateFocus(St.DirectionType.TAB_BACKWARD);
-                this._focusTrap.can_focus = true;
-                return Clutter.EVENT_STOP;
-            } else if (symbol === Clutter.KEY_Down) {
-                this._searchResults.navigateFocus(St.DirectionType.DOWN);
-                return Clutter.EVENT_STOP;
-            } else if (symbol == arrowNext && this._text.position == -1) {
-                this._searchResults.navigateFocus(nextDirection);
-                return Clutter.EVENT_STOP;
-            } else if (symbol === Clutter.KEY_Return || symbol === Clutter.KEY_KP_Enter) {
-                this._searchResults.activateDefault();
-                return Clutter.EVENT_STOP;
-            }
-        }
-        return Clutter.EVENT_PROPAGATE;
-    }
-
-    _onCapturedEvent(actor, event) {
-        if (event.type() == Clutter.EventType.BUTTON_PRESS) {
-            let source = event.get_source();
-            if (source != this._text &&
-                this._text.has_key_focus() &&
-                this._text.text == '' &&
-                !this._text.has_preedit() &&
-                !Main.layoutManager.keyboardBox.contains(source)) {
-                // the user clicked outside after activating the entry, but
-                // with no search term entered and no keyboard button pressed
-                // - cancel the search
-                this.reset();
-            }
-        }
-
-        return Clutter.EVENT_PROPAGATE;
-    }
-
-    get searchActive() {
-        return this._searchActive;
-    }
-});
index 37f65690332afefa812d9e9009781089ad74a32e..cb279c1ee56779f2e3e9dea6bbfddb716b9be210 100644 (file)
@@ -49,6 +49,7 @@ js/ui/runDialog.js
 js/ui/screenShield.js
 js/ui/screenshot.js
 js/ui/search.js
+js/ui/searchController.js
 js/ui/shellEntry.js
 js/ui/shellMountOperation.js
 js/ui/status/accessibility.js
@@ -67,7 +68,6 @@ js/ui/status/thunderbolt.js
 js/ui/status/volume.js
 js/ui/switchMonitor.js
 js/ui/unlockDialog.js
-js/ui/viewSelector.js
 js/ui/welcomeDialog.js
 js/ui/windowAttentionHandler.js
 js/ui/windowManager.js